package com.luxsoft.siipap.compras.service;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.GroupingList;

import com.luxsoft.siipap.compras.dao.EmbarcacionDao;
import com.luxsoft.siipap.compras.model.Embarcacion;
import com.luxsoft.siipap.compras.model.EntradaPorCompra;
import com.luxsoft.siipap.compras.model.RecepcionDeCompra;
import com.luxsoft.siipap.cxp.model.CXPCargo;
import com.luxsoft.siipap.cxp.model.CXPCargoAbono;
import com.luxsoft.siipap.cxp.model.CXPFactura;
import com.luxsoft.siipap.model.CantidadMonetaria;
import com.luxsoft.siipap.service.KernellSecurity;

@Transactional(propagation=Propagation.SUPPORTS,readOnly=true)
public class EmbarcacionManagerImpl implements EmbarcacionManager{
	
	private EmbarcacionDao embarcacionDao;
	
	
	public Embarcacion salvar(Embarcacion bean) {
		return doSalvar(bean, obtenerFechaDelSistema());
	}
	
	@Transactional(propagation=Propagation.REQUIRED)
	public Embarcacion doSalvar(Embarcacion bean,Date time){
		//bean=(Embarcacion)this.hibernateTemplate.load(Embarcacion.class, bean.getId());
		bean.updateData();
		for(RecepcionDeCompra r:bean.getPartidas()){
			
			//r.getLog().setModificado(time);
			/*
			if(bean.getAutorizacionAduana()!=null){				
				r.setFecha(bean.getAutorizacionAduana());
				//hibernateTemplate.initialize(r.getPartidas());
				for(EntradaPorCompra com:r.getPartidas()){
					com.setFecha(r.getFecha());
					com.setModificado(time);
				}
			}
			hibernateTemplate.save(r);*/
		}
		registrarBitacora(bean,time);
		bean=embarcacionDao.save(bean);
		return bean;
	}	
	
	@Transactional(propagation=Propagation.REQUIRED)
	public void cancelar(Embarcacion bean) {
		bean.getPartidas().clear();
		embarcacionDao.remove(bean.getId());
	}
	
	
	@Transactional(propagation=Propagation.REQUIRED)
	public Embarcacion get(Long id){
		String hql="from Embarcacion e left join fetch e.partidas p left join fetch p.partidas z " +
				" where e.id=?";
		List<Embarcacion> res=this.hibernateTemplate.find(hql,id);
		return res.get(0);
	}
	
	@Transactional(propagation=Propagation.REQUIRED)
	public void eliminar(RecepcionDeCompra rec){
		this.hibernateTemplate.delete(rec);
	}
	
	
	public EmbarcacionDao getEmbarcacionDao() {
		return embarcacionDao;
	}

	public void setEmbarcacionDao(EmbarcacionDao embarcacionDao) {
		this.embarcacionDao = embarcacionDao;
	}



	@Autowired
	private HibernateTemplate hibernateTemplate;
	
	@Autowired
	private JdbcTemplate jdbcTemplate;

	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}

	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}

	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
	public synchronized Date obtenerFechaDelSistema(){
		return (Date)getJdbcTemplate().queryForObject("select now()", Date.class);
	}
	
	@Transactional(propagation=Propagation.SUPPORTS,readOnly=false)
	private void registrarBitacora(Embarcacion bean,Date time){
		String user=KernellSecurity.instance().getCurrentUserName();	
		String ip=KernellSecurity.getIPAdress();
		String mac=KernellSecurity.getMacAdress();
		
		bean.getLog().setModificado(time);
		bean.getLog().setUpdateUser(user);
		bean.getAddresLog().setUpdatedIp(ip);
		bean.getAddresLog().setUpdatedMac(mac);
		
		
		if(bean.getId()==null){
			bean.getLog().setCreado(time);
			bean.getLog().setCreateUser(user);
			bean.getAddresLog().setCreatedIp(ip);
			bean.getAddresLog().setUpdatedMac(mac);
		}
		
	}

	@Transactional(propagation=Propagation.REQUIRED)
	public void actualizarCostos(Long id){
		Embarcacion e=get(id);
		boolean especial=e.getProveedor().isCosteoEspecial();
		String hql="from CXPCargoAbono f where f.embarcacion.id=?";
		List<CXPCargoAbono> cargos=getHibernateTemplate().find(hql,e.getId());
		
		CantidadMonetaria importe=CantidadMonetaria.pesos(0);
		for(CXPCargoAbono fac:cargos){
			if(fac instanceof CXPCargo)
				importe=importe.add(fac.getImporteMN());
			else{
				importe=importe.subtract(fac.getImporteMN());
			}
		}
		e.setImporteFacturado(importe.amount());
		
		final CantidadMonetaria valor=importe
			.add(CantidadMonetaria.pesos(e.getDta()))
			.add(CantidadMonetaria.pesos(e.getPreValidacion()));
		e.setFactorUtilidad(e.getProveedor().getMargenVenta());
		
		EventList<EntradaPorCompra> source=new BasicEventList<EntradaPorCompra>();		
		
		double toneladas=0;
		for(RecepcionDeCompra rec:e.getPartidas()){
			for(EntradaPorCompra com:rec.getPartidas()){
				if(especial){
					double tn=com.getToneladasNeta().doubleValue();
					double tc=com.getToneladaEstimada().doubleValue();
					double ton=Math.min(tn, tc);
					toneladas+=ton;
				}else{
					toneladas+=com.getToneladasNeta().doubleValue();
				}
				
				source.add(com);
			}			
		}
		GroupingList<EntradaPorCompra> grupos=
			new GroupingList<EntradaPorCompra>(source,GlazedLists.beanPropertyComparator(EntradaPorCompra.class, "producto.clave"));
		
		for(List<EntradaPorCompra> grupo:grupos){
			double toneladasPorClave=0;
			double cantidadPorClave=0;
			for(EntradaPorCompra com:grupo){
				double ton=com.getToneladasNeta().doubleValue();
				if(especial){
					ton=Math.min(com.getToneladasNeta().doubleValue(), com.getToneladaEstimada().doubleValue());
				}
				toneladasPorClave+=ton;
				cantidadPorClave+=com.getCantidadEnUnidad();
			}
			CantidadMonetaria participacion=valor.multiply(0);
			if(toneladas>0){
				participacion=valor.multiply(toneladasPorClave).divide(toneladas);
			}
			CantidadMonetaria costoPorClave=participacion.divide(cantidadPorClave);
			for(EntradaPorCompra com:grupo){
				com.setCosto(costoPorClave.amount());
				CantidadMonetaria utilidad=costoPorClave.multiply(e.getFactorUtilidad()/100);
				com.setPrecioVenta(costoPorClave.add(utilidad).amount());
			}
		}	
		
	}
	

}


